package app

import (
	"fmt"
	"math"
	"math/rand"
	"qrsj-collect/backend/utils"
	"strconv"
	"time"

	"github.com/go-vgo/robotgo"
	"github.com/wailsapp/wails/v2/pkg/runtime"
)

// 鼠标点击键名映射 1左键 2右键 3中键
var mouseClickMap = map[int]string{
	1: "left",
	2: "right",
	3: "center",
}

// 移动 x,y,移动类型(1正常2快速3跳跃4快速+跳跃 默认1),精度(默认1.0)
func (a *App) move(taskID string, args ...string) {
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	var err error
	var precision = 1.0
	var moveType = 1
	if len(args) < 2 {
		runtime.EventsEmit(a.ctx, "setLog", "【移动】参数数量错误")
		return
	}

	targetX, err := strconv.ParseFloat(args[0], 64)
	if err != nil {
		runtime.EventsEmit(a.ctx, "setLog", "【移动】参数错误")
		return
	}
	targetY, err := strconv.ParseFloat(args[1], 64)
	if err != nil {
		runtime.EventsEmit(a.ctx, "setLog", "【移动】参数错误")
		return
	}
	if len(args) > 2 {
		moveType, err = strconv.Atoi(args[2])
		if err != nil {
			runtime.EventsEmit(a.ctx, "setLog", "【移动】参数错误")
			return
		}
		if len(args) > 3 {
			precision, err = strconv.ParseFloat(args[3], 64)
			if err != nil {
				runtime.EventsEmit(a.ctx, "setLog", "移动参数错误")
				return
			}
		}
	}
	a.MoveToTarget(taskID, targetX, targetY, precision, moveType)
}

// 延时 时长(ms)
func (a *App) delay(taskID string, args ...string) {
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) != 1 {
		runtime.EventsEmit(a.ctx, "setLog", "【延迟】参数数量错误")
		return
	}
	ms, err := strconv.Atoi(args[0])
	if err != nil {
		runtime.EventsEmit(a.ctx, "setLog", "【延迟】参数格式错误")
		return
	}
	time.Sleep(time.Duration(ms) * time.Millisecond)
}

// 随机延时 时长1,时长2 单位毫秒
func (a *App) randomDelay(taskID string, args ...string) {
	var err error
	var min, max int
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) < 1 || len(args) > 2 {
		runtime.EventsEmit(a.ctx, "setLog", "【随机延时】参数数量错误")
		return
	}
	if len(args) == 1 {
		min, err = strconv.Atoi(args[0])
		if err != nil {
			runtime.EventsEmit(a.ctx, "setLog", "【随机延时】参数格式错误")
			return
		}
		max = min
	} else {
		min, err = strconv.Atoi(args[0])
		if err != nil {
			runtime.EventsEmit(a.ctx, "setLog", "【随机延时】参数格式错误")
			return
		}
		max, err = strconv.Atoi(args[1])
		if err != nil {
			runtime.EventsEmit(a.ctx, "setLog", "【随机延时】参数格式错误")
			return
		}
	}
	if min > max {
		min, max = max, min
	}
	time.Sleep(time.Duration(rand.Intn(max-min+1)+min) * time.Millisecond)
}

// 等待 时长(s)
func (a *App) await(taskID string, args ...string) {
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) != 1 {
		runtime.EventsEmit(a.ctx, "setLog", "【等待】参数数量错误")
		return
	}
	s, err := strconv.Atoi(args[0])
	if err != nil {
		runtime.EventsEmit(a.ctx, "setLog", "【等待】参数格式错误")
		return
	}
	time.Sleep(time.Duration(s) * time.Second)
}

// 随机等待 时长1,时长2 单位秒
func (a *App) randomAwait(taskID string, args ...string) {
	var err error
	var min, max int
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) < 1 {
		runtime.EventsEmit(a.ctx, "setLog", "【随机等待】参数数量错误")
		return
	}
	if len(args) == 1 {
		min, err = strconv.Atoi(args[0])
		if err != nil {
			runtime.EventsEmit(a.ctx, "setLog", "【随机等待】参数格式错误")
			return
		}
		max = min
	} else {
		min, err = strconv.Atoi(args[0])
		if err != nil {
			runtime.EventsEmit(a.ctx, "setLog", "【随机等待】参数格式错误")
			return
		}
		max, err = strconv.Atoi(args[1])
		if err != nil {
			runtime.EventsEmit(a.ctx, "setLog", "【随机等待】参数格式错误")
			return
		}
	}
	if min > max {
		min, max = max, min
	}
	time.Sleep(time.Duration(rand.Intn(max-min+1)+min) * time.Second)
}

// 键盘按键 键名 https://github.com/go-vgo/robotgo/blob/master/docs/keys.md#keys
func (a *App) keyPress(taskID string, args ...string) {
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) != 1 {
		runtime.EventsEmit(a.ctx, "setLog", "【键盘按键】参数数量错误")
		return
	}
	robotgo.KeyPress(args[0])
}

// 键盘长按 键名,时长(ms)
func (a *App) keyPressLong(taskID string, args ...string) {
	var err error
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) != 2 {
		runtime.EventsEmit(a.ctx, "setLog", "【键盘长按】参数数量错误")
		return
	}
	ms, err := strconv.Atoi(args[1])
	if err != nil {
		runtime.EventsEmit(a.ctx, "setLog", "【键盘长按】参数格式错误")
		return
	}
	robotgo.KeyDown(args[0])
	time.Sleep(time.Duration(ms) * time.Millisecond)
	robotgo.KeyUp(args[0])
}

// 键盘连续按键 键名,次数,间隔默认50ms
func (a *App) keyPressContinuous(taskID string, args ...string) {
	var err error
	var total int
	var interval = 50
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) < 2 {
		runtime.EventsEmit(a.ctx, "setLog", "【键盘连续按键】参数数量错误(至少2个)")
		return
	}
	total, err = strconv.Atoi(args[1])
	if err != nil {
		runtime.EventsEmit(a.ctx, "setLog", "【键盘连续按键】参数格式错误")
		return
	}
	if len(args) > 2 {
		interval, err = strconv.Atoi(args[2])
		if err != nil {
			runtime.EventsEmit(a.ctx, "setLog", "【键盘连续按键】参数格式错误")
			return
		}
	}
	for i := 0; i < total; i++ {
		robotgo.KeyPress(args[0])
		time.Sleep(time.Duration(interval) * time.Millisecond)
	}
}

// 键盘按下 键名
func (a *App) keyDown(taskID string, args ...string) {
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) != 1 {
		runtime.EventsEmit(a.ctx, "setLog", "【键盘按下】参数数量错误")
		return
	}
	robotgo.KeyDown(args[0])
}

// 键盘弹起 键名
func (a *App) keyUp(taskID string, args ...string) {
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) != 1 {
		runtime.EventsEmit(a.ctx, "setLog", "【键盘弹起】参数数量错误")
		return
	}
	robotgo.KeyUp(args[0])
}

// 鼠标移动 x,y
func (a *App) mouseMove(taskID string, args ...string) {
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) != 2 {
		runtime.EventsEmit(a.ctx, "setLog", "【鼠标移动】参数数量错误")
		return
	}
	x, err := strconv.Atoi(args[0])
	if err != nil {
		runtime.EventsEmit(a.ctx, "setLog", "【鼠标移动】参数格式错误")
		return
	}
	y, err := strconv.Atoi(args[1])
	if err != nil {
		runtime.EventsEmit(a.ctx, "setLog", "【鼠标移动】参数格式错误")
		return
	}
	robotgo.Move(x, y)
}

// 鼠标点击 键名,是否双击(默认false)
// 1left/2right/3center
func (a *App) mouseClick(taskID string, args ...string) {
	var err error
	var doubleClick = false
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	if len(args) < 1 {
		runtime.EventsEmit(a.ctx, "setLog", "【鼠标点击】参数数量错误")
		return
	}
	keyCode, err := strconv.Atoi(args[0])
	if err != nil {
		runtime.EventsEmit(a.ctx, "setLog", "【鼠标点击】参数格式错误")
		return
	}
	// 判断是否存在
	if _, exists := mouseClickMap[keyCode]; !exists {
		runtime.EventsEmit(a.ctx, "setLog", "【鼠标点击】键名不存在")
		return
	}
	if len(args) > 1 {
		doubleClick, err = strconv.ParseBool(args[1])
		if err != nil {
			runtime.EventsEmit(a.ctx, "setLog", "【鼠标点击】参数格式错误")
			return
		}
	}
	robotgo.Click(mouseClickMap[keyCode], doubleClick)
}

// 返回原点 移动类型(1正常2快速3跳跃默认1),精度(默认1.0)
func (a *App) returnCenter(taskID string, args ...string) {
	if _, exists := a.tasks[taskID]; !exists {
		return
	}
	var err error
	var moveType = 1
	var precision = 1.0
	if len(args) > 0 {
		moveType, err = strconv.Atoi(args[0])
		if err != nil {
			runtime.EventsEmit(a.ctx, "setLog", "【返回原点】参数格式错误")
			return
		}
		if len(args) > 1 {
			precision, err = strconv.ParseFloat(args[1], 64)
			if err != nil {
				runtime.EventsEmit(a.ctx, "setLog", "【返回原点】参数格式错误")
				return
			}
		}
	}
	a.MoveToTarget(taskID, float64(a.initCoordInfo.X), float64(a.initCoordInfo.Y), precision, moveType)
}

// 命令映射
func (a *App) commandsFunc() map[string]func(taskID string, args ...string) {
	var commands = map[string]func(taskID string, args ...string){
		"移动":     a.move, // 完成
		"延时":     a.delay,
		"随机延时":   a.randomDelay,
		"等待":     a.await,
		"随机等待":   a.randomAwait,
		"键盘按键":   a.keyPress,
		"键盘长按":   a.keyPressLong,
		"键盘连续按键": a.keyPressContinuous,
		"键盘按下":   a.keyDown,
		"键盘弹起":   a.keyUp,
		"鼠标移动":   a.mouseMove,
		"鼠标点击":   a.mouseClick,
		"返回原点":   a.returnCenter,
	}
	return commands
}

// MoveToTarget 移动到目标位置
func (a *App) MoveToTarget(taskID string, targetX, targetY, precision float64, moveType int) {
	var lastX, lastY float64
	lastMoveTime := time.Now()
	for {
		currentX := float64(a.coordInfo.X)
		currentY := float64(a.coordInfo.Y)
		angleA := float64(a.angleInfo.A)
		angleB := float64(a.angleInfo.B)
		if _, exists := a.tasks[taskID]; !exists {
			robotgo.KeyUp("w")
			robotgo.KeyUp("a")
			robotgo.KeyUp("s")
			robotgo.KeyUp("d")
			robotgo.KeyUp("shift")
			return
		}
		// 计算与目标的距离
		distance := math.Sqrt((targetX-currentX)*(targetX-currentX) + (targetY-currentY)*(targetY-currentY))
		// fmt.Printf("与目标的距离：%f\n", float32(distance))

		if distance <= precision {
			fmt.Println("已到达目标位置")
			break
		} else if moveType == 2 {
			if distance <= 5 {
				robotgo.KeyUp("shift")
			} else {
				robotgo.KeyDown("shift")
			}
		} else if moveType == 3 && distance > 5 {
			robotgo.KeyPress("space")
		} else if moveType == 4 {
			if distance <= 5 {
				robotgo.KeyUp("shift")
			} else {
				robotgo.KeyDown("shift")
				robotgo.KeyPress("space")
			}
		}

		// 检测是否卡住
		if math.Abs(currentX-lastX) > 0.1 || math.Abs(currentY-lastY) > 0.1 {
			lastMoveTime = time.Now()
		} else if time.Since(lastMoveTime) > 2*time.Second {
			robotgo.KeyUp("w")
			robotgo.KeyUp("a")
			robotgo.KeyUp("s")
			robotgo.KeyUp("d")
			// 随机选择避障方向
			direction := rand.Intn(4)
			switch direction {
			case 0:
				robotgo.KeyDown("w")
				time.Sleep(200 * time.Millisecond)
				robotgo.KeyPress("space")
				time.Sleep(1000 * time.Millisecond)
				robotgo.KeyUp("w")
			case 1:
				robotgo.KeyDown("a")
				time.Sleep(200 * time.Millisecond)
				robotgo.KeyPress("space")
				time.Sleep(1000 * time.Millisecond)
				robotgo.KeyUp("a")
			case 2:
				robotgo.KeyDown("s")
				time.Sleep(200 * time.Millisecond)
				robotgo.KeyPress("space")
				time.Sleep(1000 * time.Millisecond)
				robotgo.KeyUp("s")
			case 3:
				robotgo.KeyDown("d")
				time.Sleep(200 * time.Millisecond)
				robotgo.KeyPress("space")
				time.Sleep(1000 * time.Millisecond)
				robotgo.KeyUp("d")
			}
			lastMoveTime = time.Now()
		}

		lastX, lastY = currentX, currentY

		// 计算角度和角度差
		currentAngle := utils.GetThetaDeg(angleA, angleB)
		targetAngle := utils.CalculateVerticalAngle(currentX, currentY, targetX, targetY)
		angleDiff := targetAngle - currentAngle
		// 确保角度差在 -180 到 180 之间
		if angleDiff > 180 {
			angleDiff -= 360
		} else if angleDiff < -180 {
			angleDiff += 360
		}
		if angleDiff > -45 && angleDiff <= 45 {
			robotgo.KeyUp("s")
			robotgo.KeyDown("w")
		} else if angleDiff > 45 && angleDiff <= 135 {
			robotgo.KeyUp("a")
			robotgo.KeyDown("d")
		} else if angleDiff > -135 && angleDiff <= -45 {
			robotgo.KeyUp("d")
			robotgo.KeyDown("a")
		} else {
			robotgo.KeyUp("w")
			robotgo.KeyDown("s")
		}
		time.Sleep(50 * time.Millisecond)
	}
	robotgo.KeyUp("w")
	robotgo.KeyUp("a")
	robotgo.KeyUp("s")
	robotgo.KeyUp("d")
	robotgo.KeyUp("shift")
}
